<?php
/**
 * 模板解析类
 * Author: Dcr
 * Date: 2019/7/18
 * Time: 11:52
 */
namespace dcr\classes;
defined('IN_DCR') or exit('No permission resources.');


class TeamplateClass{

    static $instance = null;
    protected function __construct(){
    }

    /**
     * 获取实例
     * @return TeamplateClass|null
     */
    static function getInstance(){
        if( is_null(self::$instance) ){
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * 解析编译模板
     * @param $source
     * @return string
     * @throws \Exception
     */
    function template($source) {
        //编译后的文件路径
        $compile = APP_PATH . "/runtime/tpl/".md5($source).'.php';
        if(!is_file($source)) {
            throw new \Exception("Error: template source '{$source}' is not exist!");
        }
        if(APP_DEBUG || !is_file($compile) || filemtime($source) > filemtime($compile)) {
            $this->template_compile($source, $compile);
        }
        return $compile;
    }

    function template_compile($from, $to, $inmodule = false) {
        $path = dirname($to);
        if (!is_dir($path)) {
            $this->mkdirs($path);
        }
        $content = $this->template_parse(file_get_contents($from), $inmodule);
        file_put_contents($to, $content);
    }

    function template_parse($str, $inmodule = false) {
        $str = preg_replace('/<!--{(.+?)}-->/s', '{$1}', $str);
        $str = preg_replace('/{template\s+(.+?)}/', '<?php include \dcr\classes\TeamplateClass::getInstance()->template($1);?>', $str);
        $str = preg_replace('/{php\s+(.+?)}/', '<?php $1?>', $str);
        $str = preg_replace('/{if\s+(.+?)}/', '<?php if($1) { ?>', $str);
        $str = preg_replace('/{else}/', '<?php } else { ?>', $str);
        $str = preg_replace('/{else ?if\s+(.+?)}/', '<?php } else if($1) { ?>', $str);
        $str = preg_replace('/{\/if}/', '<?php } ?>', $str);
        $str = preg_replace('/{loop\s+(\S+)\s+(\S+)}/', '<?php if(is_array($1)) { foreach($1 as $2) { ?>', $str);
        $str = preg_replace('/{loop\s+(\S+)\s+(\S+)\s+(\S+)}/', '<?php if(is_array($1)) { foreach($1 as $2 => $3) { ?>', $str);
        $str = preg_replace('/{\/loop}/', '<?php } } ?>', $str);
        $str = preg_replace('/{(\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)}/', '<?php echo $1;?>', $str);
        $str = preg_replace('/{(\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff\[\]\'\"\$]*)}/', '<?php echo $1;?>', $str);
        $str = preg_replace_callback('/<\?php([^\?]+)\?>/s', function($matches){return $this->template_addquote($matches);}, $str);
        $str = preg_replace('/{([A-Z_\x7f-\xff][A-Z0-9_\x7f-\xff]*)}/s', '<?php echo $1;?>', $str);
        $str = str_replace('{##', '{', $str);
        $str = str_replace('##}', '}', $str);
        $str = "<?php defined('IN_DCR') or exit('No permission resources.');?>" . $str;
        return $str;
    }

    function template_addquote($matchs) {
        $code = "<?php {$matchs[1]}?>";
        $code = preg_replace('/\[([a-zA-Z0-9_\-\.\x7f-\xff]+)\](?![a-zA-Z0-9_\-\.\x7f-\xff\[\]]*[\'"])/s', "['$1']", $code);
        return str_replace('\\\"', '\"', $code);
    }

    function mkdirs($path) {
        if (!is_dir($path)) {
            $this->mkdirs(dirname($path));
            mkdir($path);
        }
        return is_dir($path);
    }


}